home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / pcl / src-16f.lha / ldb / backtrace.c < prev    next >
C/C++ Source or Header  |  1991-11-06  |  6KB  |  223 lines

  1. /* $Header: backtrace.c,v 1.7 90/10/22 12:38:28 wlott Exp $
  2.  *
  3.  * Simple backtrace facility.  More or less from Rob's lisp version.
  4.  */
  5.  
  6. #include <stdio.h>
  7. #include <signal.h>
  8. #include "ldb.h"
  9. #include "lisp.h"
  10. #include "globals.h"
  11. #include "interrupt.h"
  12. #include "lispregs.h"
  13.  
  14. /* Sigh ... I know what the call frame looks like and it had
  15.    better not change. */
  16.  
  17. struct call_frame {
  18.     struct call_frame *old_cont;
  19.     lispobj saved_lra;
  20.         lispobj code;
  21.     lispobj other_state[5];
  22. };
  23.  
  24. struct call_info {
  25.     struct call_frame *frame;
  26.     int interrupted;
  27.     struct code *code;
  28.     lispobj lra;
  29.     int pc; /* Note: this is the trace file offset, not the actual pc. */
  30. };
  31.  
  32. #define HEADER_LENGTH(header) ((header)>>8)
  33.  
  34. static struct code *
  35. code_pointer(object)
  36. lispobj object;
  37. {
  38.     lispobj *headerp, header;
  39.     int type, len;
  40.  
  41.     headerp = (lispobj *) PTR(object);
  42.     header = *headerp;
  43.     type = TypeOf(header);
  44.  
  45.     switch (type) {
  46.         case type_CodeHeader:
  47.             break;
  48.         case type_ReturnPcHeader:
  49.         case type_FunctionHeader:
  50.         case type_ClosureFunctionHeader:
  51.             len = HEADER_LENGTH(header);
  52.             if (len == 0)
  53.                 headerp = NULL;
  54.             else
  55.                 headerp -= len;
  56.             break;
  57.         default:
  58.             headerp = NULL;
  59.     }
  60.  
  61.     return (struct code *) headerp;
  62. }
  63.  
  64. static
  65. cs_valid_pointer_p(pointer)
  66. struct call_frame *pointer;
  67. {
  68.     return (((char *) control_stack <= (char *) pointer) &&
  69.         ((char *) pointer < (char *) current_control_stack_pointer));
  70. }
  71.  
  72. static void
  73. info_from_lisp_state(info)
  74. struct call_info *info;
  75. {
  76.     info->frame = (struct call_frame *)current_control_frame_pointer;
  77.     info->interrupted = 0;
  78.     info->code = NULL;
  79.     info->lra = 0;
  80.     info->pc = 0;
  81.  
  82.     previous_info(info);
  83. }
  84.  
  85. static void
  86. info_from_sigcontext(info, csp)
  87. struct call_info *info;
  88. struct sigcontext *csp;
  89. {
  90.     unsigned long pc;
  91.  
  92.     info->interrupted = 1;
  93.     if (LowtagOf(csp->sc_regs[CODE]) == type_FunctionPointer) {
  94.         /* We tried to call a function, but crapped out before $CODE could be fixed up.  Probably an undefined function. */
  95.         info->frame = (struct call_frame *)csp->sc_regs[OCFP];
  96.         info->lra = (lispobj)csp->sc_regs[LRA];
  97.         info->code = code_pointer(info->lra);
  98.         pc = (unsigned long)PTR(info->lra);
  99.     }
  100.     else {
  101.         info->frame = (struct call_frame *)csp->sc_regs[CFP];
  102.         info->code = code_pointer(csp->sc_regs[CODE]);
  103.         info->lra = NIL;
  104.         pc = csp->sc_pc;
  105.     }
  106.     if (info->code != NULL)
  107.         info->pc = pc - (unsigned long) info->code -
  108.             (HEADER_LENGTH(info->code->header) * sizeof(lispobj));
  109.     else
  110.         info->pc = 0;
  111. }
  112.  
  113. static int
  114. previous_info(info)
  115. struct call_info *info;
  116. {
  117.     struct call_frame *this_frame;
  118.     int free;
  119.     struct sigcontext *csp;
  120.  
  121.     if (!cs_valid_pointer_p(info->frame)) {
  122.         printf("Bogus callee value (0x%08x).\n", (unsigned long)info->frame);
  123.         return 0;
  124.     }
  125.  
  126.     this_frame = info->frame;
  127.     info->lra = this_frame->saved_lra;
  128.     info->frame = this_frame->old_cont;
  129.     info->interrupted = 0;
  130.  
  131.     if (info->frame == NULL || info->frame == this_frame)
  132.         return 0;
  133.  
  134.     if (info->lra == NIL) {
  135.         /* We were interrupted.  Find the correct sigcontext. */
  136.         free = SymbolValue(FREE_INTERRUPT_CONTEXT_INDEX)>>2;
  137.         while (free-- > 0) {
  138.             csp = lisp_interrupt_contexts[free];
  139.             if ((struct call_frame *)(csp->sc_regs[CFP]) == info->frame) {
  140.                 info_from_sigcontext(info, csp);
  141.                 break;
  142.             }
  143.         }
  144.     }
  145.     else {
  146.         info->code = code_pointer(info->lra);
  147.         if (info->code != NULL)
  148.             info->pc = (unsigned long)PTR(info->lra) -
  149.                 (unsigned long)info->code -
  150.                 (HEADER_LENGTH(info->code->header) * sizeof(lispobj));
  151.         else
  152.             info->pc = 0;
  153.     }
  154.  
  155.     return 1;
  156. }
  157.  
  158. void
  159. backtrace(nframes)
  160. int nframes;
  161. {
  162.     struct call_info info;
  163.     
  164.     info_from_lisp_state(&info);
  165.  
  166.     do {
  167.         printf("<Frame 0x%08x%s, ", (unsigned long) info.frame,
  168.                 info.interrupted ? " [interrupted]" : "");
  169.         
  170.         if (info.code != (struct code *) 0) {
  171.             lispobj function;
  172.  
  173.             printf("CODE: 0x%08x, ", (unsigned long) info.code | type_OtherPointer);
  174.  
  175.             function = info.code->entry_points;
  176.             while (function != NIL) {
  177.                 struct function_header *header;
  178.                 lispobj name;
  179.  
  180.                 header = (struct function_header *) PTR(function);
  181.                 name = header->name;
  182.  
  183.                 if (LowtagOf(name) == type_OtherPointer) {
  184.                     lispobj *object;
  185.  
  186.                     object = (lispobj *) PTR(name);
  187.  
  188.                     if (TypeOf(*object) == type_SymbolHeader) {
  189.                         struct symbol *symbol;
  190.  
  191.                         symbol = (struct symbol *) object;
  192.                         object = (lispobj *) PTR(symbol->name);
  193.                     }
  194.                     if (TypeOf(*object) == type_SimpleString) {
  195.                         struct vector *string;
  196.  
  197.                         string = (struct vector *) object;
  198.                         printf("%s, ", (char *) string->data);
  199.                     } else
  200.                         printf("(Not simple string???), ");
  201.                 } else
  202.                     printf("(Not other pointer???), ");
  203.  
  204.  
  205.                 function = header->next;
  206.             }
  207.         }
  208.         else
  209.             printf("CODE: ???, ");
  210.  
  211.         if (info.lra != NIL)
  212.             printf("LRA: 0x%08x, ", (unsigned long)info.lra);
  213.         else
  214.             printf("<no LRA>, ");
  215.  
  216.         if (info.pc)
  217.             printf("PC: 0x%x>\n", info.pc);
  218.         else
  219.             printf("PC: ???>\n");
  220.  
  221.     } while (--nframes > 0 && previous_info(&info));
  222. }
  223.